package app.panchip.bleadvertiseexample;

import android.app.Activity;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.AdvertiseCallback;
import android.bluetooth.le.AdvertiseData;
import android.bluetooth.le.AdvertiseSettings;
import android.bluetooth.le.BluetoothLeAdvertiser;
import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle;
import android.os.Handler;
import android.os.Vibrator;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.example.nirjon.bledemo4_advertising.util.BLEUtil;

import static android.bluetooth.le.AdvertiseSettings.ADVERTISE_MODE_LOW_LATENCY;
import static android.bluetooth.le.AdvertiseSettings.ADVERTISE_TX_POWER_HIGH;

public class MainActivity extends Activity implements View.OnTouchListener, View.OnClickListener {

    private static final int ENABLE_BLUETOOTH = 1234;
    private static final int BLE_PAYLOAD_LENGTH = 11;
    private byte count;
    private int x_data = 0;
    private Button operateBtn;
    private Button Btn_up;
    private Button Btn_dn;
    private Button Btn_ri;
    private Button Btn_lf;
    private TextView text;
    private EditText addressInput, payloadInput;
    private EditText intervaInput;

    private BluetoothManager myManager;
    private BluetoothAdapter myAdapter;
    private BluetoothLeAdvertiser myAdvertiser;
    private AdvertiseSettings myAdvertiseSettings;
    private AdvertiseData myAdvertiseData;
    final Handler handler = new Handler();
    Vibrator vibrator;
    Runnable runnable = new Runnable() {
        @Override
        public void run() {
            // TODO Auto-generated method stub
            sendMeg(x_data);
            //Log.d("tets","hello");
            //要做的事情，这里再次调用此Runnable对象，以实现每两秒实现一次的定时器操作
            handler.postDelayed(this, 100);
        }
    };
    AdvertiseCallback myAdvertiseCallback = new AdvertiseCallback() {
        @Override
        public void onStartSuccess(AdvertiseSettings settingsInEffect) {
            super.onStartSuccess(settingsInEffect);
            Log.v("TAG", "Advertise start succeeds: " + settingsInEffect.toString());
        }

        @Override
        public void onStartFailure(int errorCode) {
            super.onStartFailure(errorCode);
            Log.v("Tag", "Advertise start failed: " + errorCode);
        }
    };

    private boolean advertising;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main_layout);

        init();
        final long finalTime = 50;
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                // TODO Auto-generated method stub
                sendMeg(x_data);
                //Log.d("tets","hello");
                //要做的事情，这里再次调用此Runnable对象，以实现每两秒实现一次的定时器操作
                handler.postDelayed(this, finalTime);
            }
        };

        handler.postDelayed(runnable, finalTime);

        vibrator = (Vibrator) getSystemService(Service.VIBRATOR_SERVICE);


    }

    public void init() {
        text = findViewById(R.id.info);
        addressInput = findViewById(R.id.input_address);
        //intervaInput = findViewById(R.id.input_interval);
        payloadInput = findViewById(R.id.input_payload);
        operateBtn = findViewById(R.id.operate);
        Btn_up = findViewById(R.id.operate_up);
        Btn_dn = findViewById(R.id.operate_dn);
        Btn_ri = findViewById(R.id.operate3_ri);
        Btn_lf = findViewById(R.id.operate3_lf);
        operateBtn.setOnTouchListener(this);
        Btn_up.setOnTouchListener(this);
        Btn_ri.setOnTouchListener(this);
        Btn_dn.setOnTouchListener(this);
        Btn_lf.setOnTouchListener(this);
        checkBluetoothState();
    }

    private void checkBluetoothState() {
        BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();

        if (!bluetoothAdapter.isEnabled()) {
            Intent intent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
            startActivityForResult(intent, ENABLE_BLUETOOTH);
        } else {
            BT_Adv_init();
        }
    }

    private void BT_Adv_init() {
        myManager = (BluetoothManager) getSystemService(BLUETOOTH_SERVICE);
        myAdapter = myManager.getAdapter();
        myAdvertiser = myAdapter.getBluetoothLeAdvertiser();

        if (!myAdapter.isMultipleAdvertisementSupported()) {
            findViewById(R.id.operate).setEnabled(false);
            text.setText("Device does not support BLE advertisement.");
            return;
        }

        myAdvertiseSettings = new AdvertiseSettings.Builder()
                .setAdvertiseMode(ADVERTISE_MODE_LOW_LATENCY)
                .setConnectable(true)
                .setTimeout(0)
                .setTxPowerLevel(ADVERTISE_TX_POWER_HIGH)
                .build();
    }


    @Override
    protected void onActivityResult(int RequestCode, int resultCode, Intent data) {
        if (RequestCode == ENABLE_BLUETOOTH) {
            switch (resultCode) {
                case RESULT_OK:
                    Toast.makeText(MainActivity.this, "蓝牙已开启", Toast.LENGTH_SHORT).show();
                    BT_Adv_init();
                    break;
                default:
                    Toast.makeText(MainActivity.this, "需开启蓝牙", Toast.LENGTH_SHORT).show();
                    MainActivity.this.finish();
            }
        }
    }

    /* -------------------------------------------------------------------------------------- */

    private static final String HEX = "0123456789abcdef";

    private byte strToByte(String str) {
        byte res = 0;
        if (str.length() == 1) {
            res = (byte) (HEX.indexOf(str) & 0xff);
        } else {
            res = (byte) ((charToByte(str.charAt(0)) << 4) | charToByte(str.charAt(1)));
        }
        return res;
    }

    private byte charToByte(char c) {
        return (byte) HEX.indexOf(c);
    }

    private String bytesToStr(byte[] bytes, int len) {
        StringBuilder builder = new StringBuilder("");
        for (int i = 0; i != len; ++i) {
            if ((int) (bytes[i] & 0xf0) == 0) {
                builder.append("0");
                builder.append(HEX.charAt(bytes[i] & 0x0f));
            } else {
                builder.append(HEX.charAt((bytes[i] >> 4) & 0x0f));
                builder.append(HEX.charAt(bytes[i] & 0x0f));
            }
            builder.append(" ");
        }
        return builder.toString();
    }

    static String byteArrToString(byte[] data) {

        char[] result = new char[data.length];
        for (int i = 0; i < data.length; i++) {
            result[i] = (char) data[i];
        }
        return new String(result);
    }

    private void sendMeg(int x) {
        if (x != 0) {
            vibrator.vibrate(50);
            advertising = false;
            //operateBtn.setText("发送");

            String rawAddress = addressInput.getText().toString();
            rawAddress = rawAddress.replace(" ", "");
            rawAddress = rawAddress.toLowerCase();
            if (rawAddress.length() < 6 || rawAddress.length() > 10) {
                Toast.makeText(MainActivity.this, "Please input address with length between 3 and 5 bytes", Toast.LENGTH_SHORT).show();
                return;
            }
            byte[] address = new byte[rawAddress.length() / 2];
            for (int i = 0; i < address.length; ++i) {
                address[i] = strToByte(rawAddress.substring(i * 2, (i + 1) * 2));
            }

            String rawPayload = payloadInput.getText().toString();

            rawPayload = rawPayload.replace(" ", "");
            rawPayload = rawPayload.toLowerCase();
            if (rawPayload.length() < 2) {
                Toast.makeText(MainActivity.this, "The payload is at least 1 byte", Toast.LENGTH_SHORT).show();
                return;
            }
            byte[] payload = new byte[rawPayload.length() / 2];
            Log.d("Tag", "payload Length:" + payload.length + "\n");
            for (int i = 0; i < payload.length; ++i) {
                payload[i] = strToByte(rawPayload.substring(i * 2, (i + 1) * 2));
            }
            payload[payload.length - 9] = (byte) count++;
            payload[payload.length - 1] = (byte) x;
            final byte[] calculatedPayload = new byte[address.length + payload.length + 5];


            //Log.d("Tag","caculate data:"+ calculatedPayload.toString());
            BLEUtil.get_rf_payload(address, address.length, payload, payload.length, calculatedPayload);
            //calculatedPayload[9] = (byte) x;


            myAdvertiseData = new AdvertiseData.Builder()
                    .addManufacturerData(65520, calculatedPayload)
                    .build();

            text.setText(bytesToStr(calculatedPayload, address.length + payload.length + 5) + " Success!");
            myAdvertiser.startAdvertising(myAdvertiseSettings, myAdvertiseData, myAdvertiseCallback);
        }
    }

    @Override
    public boolean onTouch(View v, MotionEvent event) {
        switch (v.getId()) {
            case R.id.operate:
                addressInput.setText("690001");
                payloadInput.setText("00000000000000000000000a");
                x_data = 10;
                //sendMeg(10);
                //myAdvertiser.startAdvertising(myAdvertiseSettings, myAdvertiseData, myAdvertiseCallback);
                break;
            case R.id.operate_up:
                addressInput.setText("690001");
                payloadInput.setText("000000000000000000000002");
                //Toast.makeText(MainActivity.this, "up test sccessed!", Toast.LENGTH_SHORT).show();
                x_data = 2;
                //sendMeg(2);
                //myAdvertiser.startAdvertising(myAdvertiseSettings, myAdvertiseData, myAdvertiseCallback);
                break;
            case R.id.operate3_lf:
                addressInput.setText("690001");
                payloadInput.setText("000000000000000000000004");
                //Toast.makeText(MainActivity.this, "lf test sccessed!", Toast.LENGTH_SHORT).show();
                x_data = 4;
                //sendMeg(4);
                //myAdvertiser.startAdvertising(myAdvertiseSettings, myAdvertiseData, myAdvertiseCallback);
                break;
            case R.id.operate3_ri:
                addressInput.setText("690001");
                payloadInput.setText("000000000000000000000006");
                //Toast.makeText(MainActivity.this, "ri test sccessed!", Toast.LENGTH_SHORT).show();
                x_data = 6;
                //sendMeg(6);
                //myAdvertiser.startAdvertising(myAdvertiseSettings, myAdvertiseData, myAdvertiseCallback);
                break;
            case R.id.operate_dn:
                addressInput.setText("690001");
                payloadInput.setText("000000000000000000000008");
                //Toast.makeText(MainActivity.this, "dn test sccessed!", Toast.LENGTH_SHORT).show();
                x_data = 8;
                //sendMeg(8);
                //myAdvertiser.startAdvertising(myAdvertiseSettings, myAdvertiseData, myAdvertiseCallback);
                break;
        }


        v.setBackgroundColor(Color.rgb(0, 213, 0));

        if (event.getAction() == MotionEvent.ACTION_UP) {
            try {

                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            x_data = 0;
            count = 0;
            Log.d("Tag", "in the up");
            v.setBackgroundColor(Color.rgb(213, 213, 213));
            myAdvertiser.stopAdvertising(myAdvertiseCallback);
        }
        return false;
    }

    @Override
    public void onClick(View v) {


    }
}
